﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace Uniriotec.DC.CoordDist.Centralizada
{
    public class Process
    {
        private bool isMaster = false;
        private int id = 0;
        private int port = 0;
        private BufferedReader<NetworkStream> conn;
        private Coordinator coord;

        public void Start(object startParameters)
        {
            StartProcessParamaters parameters = (StartProcessParamaters)startParameters;
            this.isMaster = parameters.IsMaster;
            this.id = parameters.Id;
            this.port = parameters.Port;
            this.coord = parameters.Coord;

            TcpListener listener = new TcpListener(IPHelper.GetIP("localhost"), port);
            listener.Start();

            conn = new BufferedReader<NetworkStream>(listener.AcceptSocket());
            
            DoWork();
        }

        private void AskToEnterCritical()
        {
            Console.WriteLine("Process " + id + " asked to enter critical");
            coord.RequestAccess(id);
        }

        private void DoNormalWork() 
        { 
            Random rnd = new Random();
            System.Threading.Thread.Sleep(rnd.Next(20, 4000));
        }

        private void DoWork()
        {
            DoNormalWork();

            int j = 0;
            while (j++ < 10)
            {
                DoNormalWork();
                AskToEnterCritical();
                WaitToEnterCritical();
                DoCriticalWork();
                ReleaseLock();
            }

            Console.Write("Process " + id + " finished doing work");
        }

        private void WaitToEnterCritical()
        {
            Console.WriteLine("Process " + id + " is waiting to enter critical");

            string message = String.Empty;

            while (message != "Liberated")
            {
                message = conn.ReadLine();
            }

        }

        private void ReleaseLock()
        {
            Console.WriteLine("Process " + id + " released lock");
            coord.Release(id);
        }

        private void DoCriticalWork()
        {
            Console.WriteLine("Process " + id + " is doing critical work");

            FileStream file = new FileStream(@"C:\centralized.txt", FileMode.Append, FileAccess.Write);
            StreamWriter writer = new StreamWriter(file);
            writer.WriteLine("Process " + id + " did critical work");
            
            System.Threading.Thread.Sleep(1500);

            writer.Flush();
            file.Close();
        }

    }

    public class StartProcessParamaters
    {
        private bool isMaster = false;
        private int id = 0;
        private int port = 0;
        private Coordinator coord;

        public Coordinator Coord
        {
            get { return coord; }
            set { coord = value; }
        }

        public int Port
        {
            get { return port; }
            set { port = value; }
        }

        public bool IsMaster
        {
            get { return isMaster; }
            set { isMaster = value; }
        }

        public int Id
        {
            get { return id; }
            set { id = value; }
        }

        public StartProcessParamaters(bool isMaster, int id, Coordinator coord, int port)
        {
            this.isMaster = isMaster;
            this.id = id;
            this.port = port;
            this.coord = coord;
        }

    }


}
